//---------------------------------------------------------------------------
/**
 * \class CFileWalker
 * \brief This is a class to recursively traverse file & directory
 * \version 0.1
 *
 * \author Woo-Hyun Kim (woorung@nhncorp.com, woorung@gmail.com)
 * \author http://blog.naver.com/wisereign .
 *
 * \date 2002/04/29
 */
//---------------------------------------------------------------------------
#include "CFileWalker.h"
//---------------------------------------------------------------------------
CFileWalker::CFileWalker()
{
	level = 0;
}
//---------------------------------------------------------------------------
CFileWalker::~CFileWalker()
{
 //
}
//---------------------------------------------------------------------------
bool CFileWalker::StartWalking(char *pszStartPath)
{
	return StartWalking(pszStartPath, -1);
}
//---------------------------------------------------------------------------
bool CFileWalker::StartWalking(char *pszStartPath, int limit)
{
	if(level>=0&&limit>=0&&level>limit) return true;

	struct stat statbuf;
	struct dirent *dirp;
	DIR *dp;
	int ret;
	char *ptr;

	if(lstat((pszStartPath),&statbuf)<0) { // stat error
		return false;
	}

	if(S_ISDIR(statbuf.st_mode)==0) { // in case of file(regular,block,char,fifo,smbolic and sockets)

		switch(statbuf.st_mode&S_IFMT) {
			case S_IFREG : return RegularProcess(pszStartPath);
			case S_IFBLK : return BlockProcess(pszStartPath); 
			case S_IFCHR : return CharProcess(pszStartPath); 
			case S_IFIFO : return FifoProcess(pszStartPath); 
			case S_IFLNK : return FlnkProcess(pszStartPath); 
			case S_IFSOCK : return SockProcess(pszStartPath); 
			case S_IFDIR : return FdirProcess(pszStartPath); 
		}
	}
	else { // in case of directory
		if(level!=0&&!DirectoryProcess(pszStartPath)) { 
		// If you're gonna return false in directory callback of class overrided by yourself,
		// this process will stop at this point and restart at the next directory.
		// If return true, you can continually walk the remainders of the current directory.
			return true;
		}

		// increase level
		level++;

		if((dp=opendir(pszStartPath))==NULL) return false;

		while((dirp=readdir(dp))!=NULL) {
			if(!strncmp(dirp->d_name,".",1)||!strncmp(dirp->d_name,"..",2)) continue;

			string newStartPath = pszStartPath;
			if(pszStartPath[strlen(pszStartPath)-1]!='/') newStartPath += "/";
			newStartPath += dirp->d_name;		

			if(!StartWalking((char *)newStartPath.c_str(), limit)) {
			// When you are finding the same file in some directory, this block will be activated.
			// If you're gonna return false in file callbacks of class overrided by yourself,
			// this process will skip the current directory and restart it in the next directory.
			// If return true, this process will continue it in the current directory.
				closedir(dp);
				break;
			}
		}	

		closedir(dp);

		// decrease level
		level--;
	}

	return true;
}
//---------------------------------------------------------------------------
bool CFileWalker::DirectoryProcess(char *pszStartPath)
{
	cout << "Directory : " << pszStartPath << endl;
	return true;
}
//---------------------------------------------------------------------------
bool CFileWalker::RegularProcess(char *pszStartPath)
{
	cout << "Regular : " << pszStartPath << endl;
	return true;
}
//---------------------------------------------------------------------------
bool CFileWalker::BlockProcess(char *pszStartPath)
{
	cout << "Block : " << pszStartPath << endl;
	return true;
}
//---------------------------------------------------------------------------
bool CFileWalker::CharProcess(char *pszStartPath)
{
	cout << pszStartPath << endl;
	return true;
}
//---------------------------------------------------------------------------
bool CFileWalker::FifoProcess(char *pszStartPath)
{
	cout << "Fifo : " << pszStartPath << endl;
	return true;
}
//---------------------------------------------------------------------------
bool CFileWalker::FlnkProcess(char *pszStartPath)
{
	cout << "Sock : " << pszStartPath << endl;
	return true;
}
//---------------------------------------------------------------------------
bool CFileWalker::SockProcess(char *pszStartPath)
{	
	cout << pszStartPath << endl;
	return true;
}
//---------------------------------------------------------------------------
bool CFileWalker::FdirProcess(char *pszStartPath)
{
	cout << "Fdir : " << pszStartPath << endl;
	return true;
}
//---------------------------------------------------------------------------
